#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include "imbus_internal.h"
#include "im_array.h"
#include "im_hash.h"

#define TYPE_FLAG_BUILT_IN          1
#define TYPE_FLAG_INSTANTIATABLE    2
#define TYPE_FLAG_FUNDAMENTAL       4
#define TYPE_FLAG_INHERITABLE       8

typedef struct _IMTypeSlot  IMTypeSlot;

struct _IMTypeSlot
{
    IMType                   type;
    IMType                   parent;           /**< type of parent >**/

    IMQuark                  qname;            /**< quark of class name, >**/
    const IMChar            *name;             /**< interned string name >**/

    IMTypeClass             *klass;            /**< a pointer to IMObjectClass structure >**/

    IMSize                   class_size;       /**< size of the class struct >**/
    IMClassInitFunc          class_init;       /**< Class initialization function >**/
    IMClassFinalizeFunc      class_finalize;   /**< Class Finalization function >**/

    IMSize                   instance_size;    /**< size of the instance struct >**/
    IMInstanceInitFunc       instance_init;
    IMInstanceFinalizeFunc   instance_finalize;

    IMInt32                  flags;
    IMInt32                  refcount;
};

/* ============================= Internal func ============================= */
static IMTypeSlot*  __find_type_slot_by_qname       (IMQuark             qname);
static IMTypeSlot*  __find_type_slot_by_name        (const IMChar       *name);
static IMTypeSlot*  __get_type_slot                 (IMType              type);

static void         __add_to_type_name_repo         (IMQuark             qname,
                                                     IMType              type);
static void         __remove_from_type_name_repo    (IMQuark             qname);
static IMTypeSlot*  __alloc_builtin_type_slot       (IMType              type);
static IMTypeSlot*  __alloc_external_type_slot      ();
static void         __free_type_slot                (IMType              type);

static void         __im_type_register_fundamental  (IMType              type,
                                                     const IMChar       *name,
                                                     IMSize              size,
                                                     IMBool              inheritable);

static IMType       __im_type_register_class_real   (IMType              parent,
                                                     IMType              type,
                                                     IMQuark             qname,
                                                     const IMTypeInfo   *info,
                                                     IMBool              instantiatable);

static void         __im_type_instance_recursive_ctor(IMTypeSlot        *slot,
                                                      IMTypeInstance    *instance);

static void         __im_type_instance_recursive_dtor(IMTypeSlot        *slot,
                                                      IMTypeInstance    *instance);

/* ============================= Internal data ============================= */
static IMPtrArray       *__type_slot_repo           = 0;
static IMHashTable      *__type_name_repo           = 0;
static IMType            __first_unused_type        = IM_MAXUINT;
static IMBool            __type_system_initialized  = FALSE;

/* ========================== Internal functions =========================== */
static IMTypeSlot*
__find_type_slot_by_qname (IMQuark qname)
{
    IMTypeSlot *slot;
    IMType type;

    _im_assert (__type_name_repo != 0);

    /* If there is no type with such name, then 0 will be returned, which is invalid type. */
    type = IM_POINTER_TO_UINT (im_hash_table_lookup (__type_name_repo, IM_UINT_TO_POINTER(qname)));

    _im_assert (type < im_ptr_array_size (__type_slot_repo));

    slot = im_ptr_array_index (__type_slot_repo, type);

    _im_assert (slot != 0);

    return slot->qname == qname ? slot : 0;
}

static IMTypeSlot*
__find_type_slot_by_name (const IMChar *name)
{
    IMQuark qname = (name ? im_quark_try_string (name) : 0);

    return qname ? __find_type_slot_by_qname (qname) : 0;
}

static IMTypeSlot*
__get_type_slot (IMType type)
{
    _im_assert (__type_slot_repo != 0);
    return (type < im_ptr_array_size (__type_slot_repo)) ?
            im_ptr_array_index (__type_slot_repo, type) : 0;
}

static void
__add_to_type_name_repo (IMQuark qname, IMType type)
{
    _im_assert (__type_name_repo != 0);
    im_hash_table_insert (__type_name_repo, IM_UINT_TO_POINTER(qname), IM_UINT_TO_POINTER(type));
}
static void
__remove_from_type_name_repo (IMQuark qname)
{
    _im_assert (__type_name_repo != 0);
    im_hash_table_remove (__type_name_repo, IM_UINT_TO_POINTER(qname));
}

static IMTypeSlot*
__alloc_builtin_type_slot (IMType type)
{
    IMTypeSlot *slot;

    _im_assert (__type_slot_repo != 0);

    if (type >= im_ptr_array_size (__type_slot_repo)) {
        im_ptr_array_set_size (__type_slot_repo, type + 1);
    }

    _im_assert (type < im_ptr_array_size (__type_slot_repo));
    _im_assert (im_ptr_array_index (__type_slot_repo, type) == 0);

    slot = im_slice_new0 (IMTypeSlot);

    slot->type = type;

    im_ptr_array_index (__type_slot_repo, type) = slot;

    return slot;
}

static IMTypeSlot*
__alloc_external_type_slot ()
{
    IMTypeSlot *slot;
    IMType      type = 0;
    IMSize      i;

    _im_assert (__type_slot_repo != 0);

    if (__first_unused_type < im_ptr_array_size (__type_slot_repo)) {
        _im_assert (im_ptr_array_index (__type_slot_repo, __first_unused_type) == 0);

        type = __first_unused_type++;

        for (;__first_unused_type < im_ptr_array_size (__type_slot_repo); ++__first_unused_type)
            if (im_ptr_array_index (__type_slot_repo, __first_unused_type) == 0)
                break;
    } else {
        type = im_ptr_array_size (__type_slot_repo);
        im_ptr_array_append (__type_slot_repo, 0);
        __first_unused_type = type + 1;
    }

    _im_assert (type < im_ptr_array_size (__type_slot_repo));
    _im_assert (im_ptr_array_index (__type_slot_repo, type) == 0);

    slot = im_slice_new0 (IMTypeSlot);

    slot->type = type;

    im_ptr_array_index (__type_slot_repo, type) = slot;

    return slot;
}

static void
__free_type_slot (IMType type)
{
    _im_assert (type < im_ptr_array_size (__type_slot_repo));
    _im_assert (im_ptr_array_index (__type_slot_repo, type));

    im_slice_delete (IMTypeSlot, (IMTypeSlot*) im_ptr_array_index (__type_slot_repo, type));

    im_ptr_array_index (__type_slot_repo, type) = 0;

    if (type < __first_unused_type)
        __first_unused_type = type;
}

static void
__im_type_register_fundamental (IMType type, const IMChar *name, IMSize size, IMBool inheritable)
{
    IMTypeSlot *slot = __alloc_builtin_type_slot (type);

    _im_assert (slot);
    _im_assert (slot->type == type);

    slot->parent           = IM_TYPE_INVALID;
    slot->qname            = im_quark_from_static_string (name);
    slot->name             = im_quark_to_string (slot->qname);
    slot->klass            = 0;
    slot->class_size       = 0;
    slot->class_init       = 0;
    slot->class_finalize   = 0;
    slot->instance_size    = size;
    slot->instance_init    = 0;
    slot->instance_finalize= 0;
    slot->flags            = TYPE_FLAG_BUILT_IN | TYPE_FLAG_FUNDAMENTAL;

    if (inheritable)
        slot->flags        |= TYPE_FLAG_INHERITABLE;

    __add_to_type_name_repo (slot->qname, type);
}

/**
 * If type == 0, then it's an user defined class. otherwise, it's a builtin class.
 */
static IMType
__im_type_register_class_real (IMType              parent,
                               IMType              type,
                               IMQuark             qname,
                               const IMTypeInfo   *info,
                               IMBool              instantiatable)
{
    IMTypeSlot      *klass_slot  = (type ? __get_type_slot (type) : 0);
    IMTypeSlot      *parent_slot = __get_type_slot (parent);

    _im_return_val_if_fail (klass_slot == 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (parent_slot != 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (qname != 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (info != 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (__find_type_slot_by_qname (qname) == 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (info->class_size != 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (info->instance_size != 0, IM_TYPE_INVALID);
    _im_return_val_if_fail (parent_slot->flags & TYPE_FLAG_INHERITABLE, IM_TYPE_INVALID);
    _im_return_val_if_fail (info->class_size >= sizeof (IMTypeClass), IM_TYPE_INVALID);
    _im_return_val_if_fail (info->instance_size >= sizeof (IMTypeInstance), IM_TYPE_INVALID);

    if (type)
        klass_slot = __alloc_builtin_type_slot (type);
    else
        klass_slot = __alloc_external_type_slot ();

    _im_assert (klass_slot != 0);

    klass_slot->klass = (IMTypeClass *) im_slice_alloc0 (info->class_size);
    _im_assert (klass_slot->klass != 0);

    if (parent_slot->klass)
        memcpy (klass_slot->klass, parent_slot->klass, parent_slot->class_size);

    klass_slot->klass->type       = klass_slot->type;
    klass_slot->parent             = parent;
    klass_slot->qname              = qname;
    klass_slot->name               = im_quark_to_string (qname);

    klass_slot->class_size         = info->class_size;
    klass_slot->class_init         = info->class_init;
    klass_slot->class_finalize     = info->class_finalize;

    klass_slot->instance_size      = info->instance_size;
    klass_slot->instance_init      = info->instance_init;
    klass_slot->instance_finalize  = info->instance_finalize;

    klass_slot->flags              = TYPE_FLAG_INHERITABLE;

    if (instantiatable)
        klass_slot->flags          |= TYPE_FLAG_INSTANTIATABLE;
    if (type)
        klass_slot->flags          |= TYPE_FLAG_BUILT_IN;

    klass_slot->refcount           = 0;

    ++ parent_slot->refcount;

    __add_to_type_name_repo (qname, klass_slot->type);

    if (info->class_init)
        info->class_init (klass_slot->klass);

    return klass_slot->type;
}

static void
__im_type_instance_recursive_ctor (IMTypeSlot *slot, IMTypeInstance *instance)
{
    if (slot->parent)
        __im_type_instance_recursive_ctor (__get_type_slot (slot->parent), instance);

    /* The instance is not constructed yet, so overriding of virtual
     * functions shouldn't take effect here.
     */
    if (slot->instance_init) {
        instance->klass = slot->klass;
        slot->instance_init (instance);
    }
}

static void
__im_type_instance_recursive_dtor (IMTypeSlot *slot, IMTypeInstance *instance)
{
    /* The derived instance has been destructed already, so overriding of virtual
     * functions shouldn't take effect here.
     */
    if (slot->instance_finalize) {
        instance->klass = slot->klass;
        slot->instance_finalize (instance);
    }

    if (slot->parent)
        __im_type_instance_recursive_dtor (__get_type_slot (slot->parent), instance);
}

/* ======================== IMType related functions ======================== */
void
im_type_init ()
{

    if (__type_system_initialized) return;

    __type_system_initialized = TRUE;

    __type_slot_repo = im_ptr_array_new_reserved (IM_TYPE_LAST_BUILTIN + 1);
    __type_name_repo = im_hash_table_new (im_direct_hash, 0);

    /* Register all fundamental types. */
    __im_type_register_fundamental (IM_TYPE_INVALID,     "Invalid",     0,                TRUE);
    __im_type_register_fundamental (IM_TYPE_VOID,        "Void",        0,                FALSE);
    __im_type_register_fundamental (IM_TYPE_CHAR,        "Char",        sizeof(IMChar),   FALSE);
    __im_type_register_fundamental (IM_TYPE_UCHAR,       "UChar",       sizeof(IMUChar),  FALSE);
    __im_type_register_fundamental (IM_TYPE_BOOL,        "Bool",        sizeof(IMBool),   FALSE);
    __im_type_register_fundamental (IM_TYPE_INT16,       "Int16",       sizeof(IMInt16),  FALSE);
    __im_type_register_fundamental (IM_TYPE_UINT16,      "UInt16",      sizeof(IMUInt16), FALSE);
    __im_type_register_fundamental (IM_TYPE_INT32,       "Int32",       sizeof(IMInt32),  FALSE);
    __im_type_register_fundamental (IM_TYPE_UINT32,      "UInt32",      sizeof(IMUInt32), FALSE);
    __im_type_register_fundamental (IM_TYPE_INT64,       "Int64",       sizeof(IMInt64),  FALSE);
    __im_type_register_fundamental (IM_TYPE_UINT64,      "UInt64",      sizeof(IMUInt64), FALSE);
    __im_type_register_fundamental (IM_TYPE_DOUBLE,      "Double",      sizeof(IMDouble), FALSE);
    __im_type_register_fundamental (IM_TYPE_C_STRING,    "CString",     sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_POINTER,     "Pointer",     sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_BYTE_ARRAY,  "ByteArray",   sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_BOOL_ARRAY,  "BoolArray",   sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_INT16_ARRAY, "Int16Array",  sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_UINT16_ARRAY,"UInt16Array", sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_INT32_ARRAY, "Int32Array",  sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_UINT32_ARRAY,"UInt32Array", sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_INT64_ARRAY, "Int64Array",  sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_UINT64_ARRAY,"UInt64Array", sizeof(IMPointer),FALSE);
    __im_type_register_fundamental (IM_TYPE_DOUBLE_ARRAY,"DoubleArray", sizeof(IMPointer),FALSE);

    /* Register built-in class types */
    __im_type_register_object       ();
    __im_type_register_initially_owned();
    __im_type_register_value        ();
    __im_type_register_value_array  ();
    __im_type_register_object_array ();
    __im_type_register_object_queue ();
    __im_type_register_memory_chunk ();
    __im_type_register_stream       ();
    __im_type_register_byte_stream  ();
    __im_type_register_text_stream  ();

    __im_type_register_attributes   ();
    __im_type_register_attr_list    ();

    __im_type_register_string       ();
    __im_type_register_text         ();
    __im_type_register_lookup_table ();
    __im_type_register_property     ();
    __im_type_register_prop_list    ();
    __im_type_register_event        ();
    __im_type_register_event_roles  ();
    __im_type_register_hotkey       ();
    __im_type_register_hotkey_profile();
    __im_type_register_io_channel   ();
    __im_type_register_io_channel_unix();
    __im_type_register_connection   ();
    __im_type_register_main_loop    ();
    __im_type_register_main_loop_unix();
    __im_type_register_server       ();
    __im_type_register_server_unix  ();
    __im_type_register_address      ();
    __im_type_register_address_unix ();
    __im_type_register_module       ();
    __im_type_register_component_info   ();
}

void
__im_type_register_builtin_class (IMType              parent,
                                  IMType              type,
                                  const IMChar       *class_name,
                                  const IMTypeInfo   *type_info,
                                  IMBool              instantiatable)
{
    IMQuark qname;

    _im_return_if_fail (type);
    _im_return_if_fail (class_name && *class_name);
    _im_return_if_fail (type_info);

    qname = im_quark_from_static_string (class_name);

    __im_type_register_class_real (parent, type, qname, type_info, instantiatable);
}

IMType
im_type_register_class (IMType              parent,
                        const IMChar       *class_name,
                        const IMTypeInfo   *type_info,
                        IMBool              instantiatable)
{
    IMQuark qname;

    _im_return_if_fail (class_name && *class_name);
    _im_return_if_fail (type_info);

    qname = im_quark_from_string (class_name);

    return __im_type_register_class_real (parent, 0, qname, type_info, instantiatable);
}

IMBool
im_type_deregister_class (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);

    _im_return_val_if_fail (slot, FALSE);
    _im_return_val_if_fail (slot->klass, FALSE);

    if (slot->flags & (TYPE_FLAG_BUILT_IN | TYPE_FLAG_FUNDAMENTAL)) {
        _im_warn ("%s is a built-in type, so it can't be deregistered.\n", slot->name);
        return FALSE;
    }

    if (slot->refcount > 0) {
        _im_warn ("%s is used by others, so it can't be deregistered.\n", slot->name);
        return FALSE;
    }

    if (slot->class_finalize)
        slot->class_finalize (slot->klass);

    if (slot->parent) {
        IMTypeSlot *parent_slot = __get_type_slot (slot->parent);
        _im_assert (parent_slot);
        _im_assert (parent_slot->refcount > 0);
        -- parent_slot->refcount;
    }

    __remove_from_type_name_repo (slot->qname);

    im_slice_free (slot->class_size, slot->klass);

    __free_type_slot (type);

    return TRUE;
}

const IMChar*
im_type_get_name (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);

    return slot ? slot->name : "Invalid";
}

IMType
im_type_from_name (const IMChar *name)
{
    IMTypeSlot *slot = __find_type_slot_by_name (name);

    return slot ? slot->type : IM_TYPE_INVALID;
}

IMType
im_type_get_parent (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);

    return slot ? slot->parent : IM_TYPE_INVALID;
}

IMBool
im_type_is_fundamental (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return slot ? ((slot->flags & TYPE_FLAG_FUNDAMENTAL) != 0) : FALSE;
}

IMBool
im_type_is_built_in (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return slot ? ((slot->flags & TYPE_FLAG_BUILT_IN) != 0) : FALSE;
}

IMBool
im_type_is_instantiatable (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return slot ? ((slot->flags & TYPE_FLAG_INSTANTIATABLE) != 0) : FALSE;
}

IMSize
im_type_get_instance_size (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return slot ? slot->instance_size : 0;
}

IMBool
im_type_is_a (IMType type, IMType is_a_type)
{
    IMTypeSlot *slot;

    if (is_a_type == IM_TYPE_INVALID)
        return FALSE;

    slot = __get_type_slot (type);

    for (; slot && slot->type != IM_TYPE_INVALID; slot = __get_type_slot (slot->parent))
        if (slot->type == is_a_type)
            return TRUE;

    return FALSE;
}

IMBool
im_type_is_referenced (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return (slot != 0) ? (slot->refcount != 0) : FALSE;
}

IMBool
im_type_is_valid (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return slot != 0 && slot->type == type;
}

/* ===================== IMTypeClass related functions ==================== */
IMBool
im_type_class_valid (IMConstPointer klass)
{
    const IMTypeClass *cp = (const IMTypeClass*) klass;
    IMTypeSlot *slot;

    if (!cp || !cp->type)
        return FALSE;

    slot = __get_type_slot (cp->type);

    return slot && slot->type == cp->type && slot->klass == cp;
}

const IMChar*
im_type_class_get_name (IMConstPointer klass)
{
    _im_return_val_if_fail (im_type_class_valid (klass), 0);

    return im_type_get_name (((const IMTypeClass *)klass)->type);
}

IMType
im_type_class_get_type (IMConstPointer klass)
{
    _im_return_val_if_fail (im_type_class_valid (klass), IM_TYPE_INVALID);

    return ((const IMTypeClass *)klass)->type;
}

IMConstPointer
im_type_class_get_parent (IMConstPointer klass)
{
    _im_return_val_if_fail (im_type_class_valid (klass), 0);

    return im_type_class_from_type (im_type_get_parent (((const IMTypeClass *)klass)->type));
}

IMConstPointer
im_type_class_from_name (const IMChar *name)
{
    IMTypeSlot *slot = __find_type_slot_by_name (name);
    return slot ? slot->klass : 0;
}

IMConstPointer
im_type_class_from_type (IMType type)
{
    IMTypeSlot *slot = __get_type_slot (type);
    return slot ? slot->klass : 0;
}

IMBool
im_type_class_is_a (IMConstPointer klass, IMType is_a_type)
{
    return im_type_is_a (im_type_class_get_type (klass), is_a_type);
}

IMConstPointer
im_type_class_check_cast (IMConstPointer klass, IMType is_a_type)
{
    return im_type_class_is_a (klass, is_a_type) ? klass : 0;
}

IMSize
im_type_class_sizeof (IMConstPointer klass)
{
    IMTypeSlot *slot = __get_type_slot (im_type_class_get_type (klass));
    return slot ? slot->class_size : 0;
}

/* ======================== IMTypeInstance related functions ===================== */
IMPointer
im_type_instance_new (IMType type)
{
    IMTypeInstance  *instance;
    IMTypeSlot      *slot = __get_type_slot (type);

    _im_return_val_if_fail (slot, 0);

    if ((slot->flags & TYPE_FLAG_INSTANTIATABLE) == 0) {
        _im_warn ("Can not create new instance of non-instantiatable type %s.\n", slot->name);
        return 0;
    }

    instance = (IMTypeInstance *) im_slice_alloc0 (slot->instance_size);
    _im_assert (instance);

#if IM_ENABLE_DEBUG
    _im_verbose ("%p: %s: im_type_instance_new(%u)\n", (IMPointer) instance, slot->name, slot->instance_size);
#endif

    __im_type_instance_recursive_ctor (slot, instance);

    instance->klass = slot->klass;

    ++ slot->refcount;

    return instance;
}

void
im_type_instance_delete (IMPointer instance)
{
    IMType type;
    IMTypeSlot *slot;

    _im_return_if_fail (instance);
    type = im_type_instance_get_type (instance);
    _im_return_if_fail (type);
    slot = __get_type_slot (type);
    _im_return_if_fail (slot && slot->type == type);

#if IM_ENABLE_DEBUG
    _im_verbose ("%p: %s: im_type_instance_delete(%u)\n", (IMPointer) instance, slot->name, slot->instance_size);
#endif

    __im_type_instance_recursive_dtor (slot, instance);

    im_slice_free (slot->instance_size, instance);
    -- slot->refcount;
}

IMSize
im_type_instance_sizeof (IMConstPointer instance)
{
    IMTypeSlot *slot = __get_type_slot (im_type_instance_get_type (instance));

    return slot ? slot->instance_size : 0;
}

IMBool
im_type_instance_valid (IMConstPointer instance)
{
    IMType type = im_type_instance_get_type (instance);

    return type != IM_TYPE_INVALID && __get_type_slot (type) != 0;
}

IMType
im_type_instance_get_type (IMConstPointer instance)
{
    const IMTypeClass *klass = im_type_instance_get_class (instance);

    return klass ? klass->type : 0;
}

IMConstPointer
im_type_instance_get_class (IMConstPointer instance)
{
    const IMTypeInstance *ip = (const IMTypeInstance*) instance;

    return (ip && im_type_class_valid (ip->klass)) ? ip->klass : 0;
}

IMBool
im_type_instance_is_a (IMConstPointer instance, IMType is_a_type)
{
    return im_type_is_a (im_type_instance_get_type (instance), is_a_type);
}

IMPointer
im_type_instance_check_cast (IMPointer instance, IMType is_a_type)
{
    return im_type_instance_is_a (instance, is_a_type) ? instance : 0;
}

IMConstPointer
im_type_instance_check_cast_const (IMConstPointer instance, IMType is_a_type)
{
    return im_type_instance_is_a (instance, is_a_type) ? instance : 0;
}

static void
__printf_type_slot (IMPointer s, IMPointer u)
{
    IMTypeSlot *slot = (IMTypeSlot *)s;

    if (slot) {
        fprintf (stderr, "%3u: %-22s: %s %s %s %s : Class size = %-3u  Instance size = %-3u  Reference = %-3u  Parent = %s\n",
                slot->type,
                slot->name,
                (slot->flags & TYPE_FLAG_BUILT_IN) ? "B" : " ",
                (slot->flags & TYPE_FLAG_FUNDAMENTAL) ? "F" : " ",
                (slot->flags & TYPE_FLAG_INSTANTIATABLE) ? "I" : " ",
                (slot->flags & TYPE_FLAG_INHERITABLE) ? "C" : " ",
                slot->class_size,
                slot->instance_size,
                slot->refcount,
                im_type_get_name (slot->parent));
    }
}

void
im_type_print_all_type_informations ()
{
    _im_return_if_fail (__type_system_initialized);

    fprintf (stderr, "All types: B = Built-in  F = Fundamental  I = Instantiatable  C = Inheritable.\n");

    im_ptr_array_foreach (__type_slot_repo, __printf_type_slot, 0);
}
/*
vi:ts=4:nowrap:ai:expandtab
*/
